
    /**  
    * @Title: LockAspectHandler.java
    * @Package com.efast.cafe.framework.redis.locker
    * @Description: TODO(用一句话描述该文件做什么)
    * @author Administrator
    * @date 2019年1月18日
    * @version V1.0  
    */
    
package com.efast.cafe.framework.redis.locker;

import java.util.concurrent.TimeUnit;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.efast.cafe.framework.enums.ResultStatus;
import com.efast.cafe.framework.exception.ServiceException;
import com.efast.cafe.framework.redis.locker.annotation.CafeLock;
import com.efast.cafe.framework.spring.SpringContextUtils;

/**
    * @ClassName: LockAspectHandler
    * @Description: 并发锁aop拦截，请将注解使用在controller 方法上。
    * @author xuanming.feng
    * @date 2019年1月18日
    *
    */
@Aspect
@Component
public class LockAspectHandler {

	private static String LOCKER_FRX="locker:";
	
	@Autowired
	private BusinessKeyProvider businessKeyProvider;
	
	@Around(value = "@annotation(cafeLock)")
	public Object around(ProceedingJoinPoint joinPoint,CafeLock cafeLock)throws Throwable{
			String keyGroup = cafeLock.keyGroup();
			String keyName =  LOCKER_FRX+cafeLock.name()+businessKeyProvider.getKeyName(joinPoint, cafeLock);
			RedissonDistributedLocker locker = null;
			boolean isLocked = false;
			try{
				locker = LockerFactory.getLocker(keyGroup);
				isLocked = locker.tryLock(keyName, cafeLock.waitTime(), cafeLock.leaseTime(),TimeUnit.SECONDS);
				if(isLocked)
					return joinPoint.proceed();
				else
					throw new ServiceException(ResultStatus.SYS_BUSY.getCode(),ResultStatus.SYS_BUSY.getMessage());
			}finally{
				if(locker!=null && isLocked)
					locker.unlock(keyName);
			}
		
	}
}
